<script setup lang="ts">
import { FormInfo, ChartResults } from "@/views/resourceAccess/components";
import { reactive, ref, watch } from "vue";
import { chartResults, formInfo } from "../components/interface";
import { http } from "@/utils/http";
import dataMock from "./assets/dataMock.json";

const formProps: formInfo = reactive({
  title: "模型迁移",
  btnNames: ["开始计算", "暂停", "结束"],
  btnDisabled: [false, false, false],
  formInfoList: [
    {
      id: 1,
      title: "待处理任务选择",
      inputType: "0",
      options: [
        {
          value: "CNN&EMNIST",
          label: "CNN&EMNIST"
        },
        {
          value: "AlexNet&CIFAR10",
          label: "AlexNet&CIFAR10"
        },
        {
          value: "VGG16&IMAGE100",
          label: "VGG16&IMAGE100"
        }
      ]
    },
    {
      id: 2,
      title: "配置文件",
      inputType: "1",
      options: undefined
    },
    {
      id: 3,
      title: "基准训练方法",
      inputType: "0",
      options: [
        {
          value: "FedSwap",
          label: "FedSwap"
        },
        {
          value: "FedAvg",
          label: "FedAvg"
        }
      ]
    },
    {
      id: 4,
      title: "优化训练方法",
      inputType: "0",
      options: [
        {
          value: "FedMigr",
          label: "FedMigr"
        }
      ]
    }
  ]
});
const chartResultsProps: chartResults = reactive({
  header: ["epoch1:  -142.1546", "epoch1:  -82.1546"],
  result: "优化训练方法比基准训练方法在相同准确率下至少节省30%训练时间",
  chartSelect: [0, 0],
  chartData: [
    {
      title: "模型精度",
      legend: ["基准训练方法", "优化训练方法"],
      xAxisName: "",
      xAxisData: ["20", "40", "80", "100", "120", "140", "160", "180", "200"],
      yAxisSetting: {
        min: 0,
        max: 1,
        interval: 0.2
      },
      seriesData: [
        {
          name: "基准训练方法",
          data: [0.6, 0.79, 0.4, 0.8, 0.65]
        },
        {
          name: "优化训练方法",
          data: [0.45, 0.35, 0.6, 0.55, 0.75]
        }
      ]
    },
    {
      title: "资源消耗",
      legend: ["基准训练方法", "优化训练方法"],
      xAxisName: "",
      xAxisData: ["20", "40", "80", "100", "120", "140", "160", "180", "200"],
      yAxisSetting: {},
      seriesData: [
        {
          name: "基准训练方法",
          type: "line",
          data: [2, 2.3, 1.6, 2.41, 2.1],
          symbol: "none", // 设置标记点形状为无
          showSymbol: false, // 不显示标记点
          lineStyle: {
            shadowBlur: 5,
            shadowColor: "rgba(12, 120, 225, 0.5)",
            shadowOffsetY: 3
          }
        },
        {
          name: "优化训练方法",
          type: "line",
          data: [1.7, 1.5, 2, 1.9, 2.3],
          symbol: "none", // 设置标记点形状为无
          showSymbol: false, // 不显示标记点
          lineStyle: {
            shadowBlur: 5,
            shadowColor: "rgba(255, 153, 0, 0.5)",
            shadowOffsetY: 3
          }
        }
      ]
    }
  ]
});
const initStaticChart = dataStatic => {
  const xData = [],
    seriesData0 = [[], []],
    seriesData1 = [[], []];
  dataStatic.forEach(item => {
    xData.push(item.epoch);
    seriesData0[0].push(Number(item.basic.test_acc));
    seriesData0[1].push(Number(item.opt.test_acc));
    seriesData1[0].push(Number(item.basic.time));
    seriesData1[1].push(Number(item.opt.time));
  });

  const result = dataStatic.slice(-1)[0];
  const save = (
    ((Number(result.basic.time) - Number(result.opt.time)) * Number(100)) /
    Number(result.basic.time)
  ).toFixed(2);

  chartResultsProps.header = [
    `epoch${result.epoch}: test_acc: ${result.basic.test_acc}`,
    `epoch${result.epoch}: test_acc: ${result.opt.test_acc}`
  ];
  chartResultsProps.chartData[0].xAxisData = xData;
  chartResultsProps.chartData[1].xAxisData = xData;
  chartResultsProps.chartData[0].seriesData[0]["data"] = seriesData0[0];
  chartResultsProps.chartData[0].seriesData[1]["data"] = seriesData0[1];
  chartResultsProps.chartData[1].seriesData[0]["data"] = seriesData1[0];
  chartResultsProps.chartData[1].seriesData[1]["data"] = seriesData1[1];
  chartResultsProps.result = `优化训练方法比基准训练方法在相同准确率下至少节省${save}%的资源开销`;
};
initStaticChart(dataMock);

let chartRes = [];
let intervalReq = null,
  intervalRender = null;
let hasPause = false,
  hasStop = false,
  reqStop = false;
const renderNum = ref(-1);
const interval = 1000;
const pause = ref(false);
// 开始渲染
const startRedner = () => {
  intervalRender = setInterval(() => {
    renderNum.value++;
    renderChart(chartRes, renderNum.value);
  }, interval);
};
// 暂停渲染
const pauseRender = () => {
  clearInterval(intervalRender);
  renderResult();
};
// 终止渲染
const stopRender = () => {
  pauseRender();
  clearInterval(intervalReq);
  formProps.btnNames[1] = "暂停";
  hasStop = true;
  formProps.btnDisabled[0] = false;
  formProps.btnNames[0] = "开始计算";
};
// 渲染表格
const renderChart = (dataArr: any, curNum: number) => {
  chartResultsProps.header = [
    `epoch${dataArr[curNum].epoch}: test_acc: ${dataArr[curNum].basic.test_acc}`,
    `epoch${dataArr[curNum].epoch}: test_acc: ${dataArr[curNum].opt.test_acc}`
  ];
  chartResultsProps.chartData[0].xAxisData.push(dataArr[curNum].epoch);
  chartResultsProps.chartData[0].seriesData[0]["data"].push(
    Number(dataArr[curNum].basic.test_acc)
  );
  chartResultsProps.chartData[0].seriesData[1]["data"].push(
    Number(dataArr[curNum].opt.test_acc)
  );
  chartResultsProps.chartData[1].seriesData[0]["data"].push(
    Number(dataArr[curNum].basic.time)
  );
  chartResultsProps.chartData[1].seriesData[1]["data"].push(
    Number(dataArr[curNum].opt.time)
  );
  chartResultsProps.chartData[1].xAxisData.push(dataArr[curNum].epoch);
};
// 渲染结果
const renderResult = () => {
  const result = chartRes[renderNum.value];
  const save = (
    ((Number(result.basic.time) - Number(result.opt.time)) * Number(100)) /
    Number(result.basic.time)
  ).toFixed(2);
  chartResultsProps.result = `优化训练方法比基准训练方法在相同准确率下至少节省${save}%的资源开销`;
};
// 初始化数据
const initChartData = () => {
  chartResultsProps.header = ["", ""];
  chartResultsProps.chartData[0].xAxisData = [];
  chartResultsProps.chartData[1].xAxisData = [];
  chartResultsProps.chartData[0].seriesData[0]["data"] = [];
  chartResultsProps.chartData[0].seriesData[1]["data"] = [];
  chartResultsProps.chartData[1].seriesData[0]["data"] = [];
  chartResultsProps.chartData[1].seriesData[1]["data"] = [];
  chartResultsProps.result = "";
  chartRes = [];
  renderNum.value = -1;
  intervalReq = null;
  intervalRender = null;
  pause.value = false;
  hasPause = false;
  hasStop = false;
};
const btnClick1 = async e => {
  let num = 0;
  initChartData();
  intervalReq = setInterval(async () => {
    await http.request("get", "@/../public/dataMock.json").then(res => {
      // 需要判断数据是否改变
      // 当前仅为简单模拟
      chartRes.push(res[num]);
      // 刚开始时与请求数据同步渲染
      // 若经历暂停则不再渲染
      if (!hasPause) {
        renderNum.value++;
        renderChart(chartRes, renderNum.value);
      }
      // 判断数据请求是否结束
      if (res[num++]["msg"] == "end") {
        // 请求结束后，则要清除当前的interval，并设立标志
        // 需要判断是否存在与最新数据同步
        reqStop = true;
        // 若相等则说明当前数据与最新数据同步
        if (renderNum.value == chartRes.length - 1) {
          stopRender();
        } else {
          // 否则仅清除当前定时器
          clearInterval(intervalReq);
        }
        console.log("stop");
      }
    });
  }, interval);
  formProps.btnDisabled[0] = true;
  formProps.btnNames[0] = "计算中...";
};
const btnClick2 = e => {
  // 暂停状态为true，点击按钮
  if (!hasStop) {
    if (pause.value) {
      startRedner();
    } else {
      pauseRender();
    }
    hasPause = true;
    formProps.btnNames[1] = pause.value ? "暂停" : "继续";
    pause.value = !pause.value;
  }
};
const btnClick3 = e => {
  stopRender();
};
watch(renderNum, newVal => {
  if (renderNum.value == chartRes.length) {
    renderNum.value--;
    stopRender();
  }
});
</script>

<template>
  <el-row :gutter="20">
    <el-col :span="12" style="min-height: 200px">
      <el-col style="min-height: 200px">
        <FormInfo
          :title="formProps.title"
          :btnNames="formProps.btnNames"
          :formInfoList="formProps.formInfoList"
          :btnDisabled="formProps.btnDisabled"
          @btnClick1="btnClick1"
          @btnClick2="btnClick2"
          @btnClick3="btnClick3"
        />
      </el-col>
    </el-col>
    <el-col :span="12" style="min-height: 200px">
      <el-col style="min-height: 200px">
        <ChartResults
          :header="chartResultsProps.header"
          :chartSelect="chartResultsProps.chartSelect"
          :chartData="chartResultsProps.chartData"
          :result="chartResultsProps.result"
        />
      </el-col>
    </el-col>
  </el-row>
</template>
